package com.redis;

/**
 * 分布式锁
 */
public class RedisLock {
    private Redis redis;
    private String lockKey;
    private int waitTime;
    private static final Integer DEFAULT_ACQUIRY_RESOLUTION_MILLIS = 100;
    private volatile boolean isLock;

    public RedisLock(Redis redis, String lockKey) {
        this.waitTime = 10000;
        this.isLock = false;
        this.redis = redis;
        this.lockKey = lockKey + "_lock";
    }

    public RedisLock(Redis redis, String lockKey, int waitTime) {
        this(redis, lockKey);
        this.waitTime = waitTime;
    }

    public String getLockKey() {
        return this.lockKey;
    }

    private String get(String key) {
        return this.redis.getString(key);
    }

    private long setNx(String key, String value) {
        return this.redis.setnx(key, value);
    }

    private String getSet(String key, String value) {
        return this.redis.getSet(key, value);
    }

    public boolean lock() throws InterruptedException {
        int waitTime = this.waitTime;
        Integer retryCount = waitTime / DEFAULT_ACQUIRY_RESOLUTION_MILLIS + 1;
        int currentRetryCount = 0;

        do {
            ++currentRetryCount;
            String code = this.redis.set(this.lockKey, String.valueOf(System.currentTimeMillis()), "NX", "PX", (long) waitTime);
            if ("OK".equals(code)) {
                this.isLock = true;
                return true;
            }

            Thread.sleep((long) DEFAULT_ACQUIRY_RESOLUTION_MILLIS);
        } while (currentRetryCount < retryCount);

        return false;
    }

    public void unLock() {
        if (this.isLock) {
            this.redis.delete(this.lockKey);
            this.isLock = false;
        }

    }
}
